﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace MadLibrary.Net.Client
{
    /// <summary>
    /// Supports requesting to target by network.
    /// </summary>
    public class Requester
    {
        /// <summary>
        /// The target for requesting.
        /// </summary>
        public IPEndPoint Target { get; set; }
        /// <summary>
        /// Provides all network communications of current requester.
        /// </summary>
        protected Socket Communicator { get; set; }
        /// <summary>
        /// Creates new Requester object instance and sets Target to loopback address on port 80.
        /// </summary>
        public Requester()
        {
            this.Target = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80);
            this.Communicator = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        /// <summary>
        /// Creates new Requester object instance and sets target into value specified.
        /// </summary>
        /// <param name="Target">Specifies target for requesting.</param>
        public Requester(IPEndPoint Target)
        {
            this.Target = Target;
            this.Communicator = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        /// <summary>
        /// Serves as connection base. Doesn't have to be overrided.
        /// </summary>
        public virtual void Connect()
        {
            this.Communicator.Connect(this.Target);
        }
        /// <summary>
        /// Serves as base for sending data to target and sets send time.
        /// </summary>
        /// <param name="data">Specifies data to send.</param>
        public virtual void Send(Request data)
        {
            data.Time = DateTime.Now;
            this.Communicator.Send(Encoding.ASCII.GetBytes(data.Message));
        }
        /// <summary>
        /// Serves as base for receiving response from target.
        /// </summary>
        /// <returns>Response received from target.</returns>
        public virtual Response Receive()
        {
            byte[] data = new byte[1024];
            this.Communicator.Receive(data);
            return new Response(Encoding.ASCII.GetString(data), DateTime.Now);
        }
        /// <summary>
        /// Serves as base for receiving response of specified length from target.
        /// </summary>
        /// <param name="length">Specifies length of response.</param>
        /// <returns>Response received from target.</returns>
        public virtual Response Receive(int length)
        {
            byte[] data = new byte[length];
            this.Communicator.Receive(data);
            return new Response(Encoding.ASCII.GetString(data), DateTime.Now);
        }
        /// <summary>
        /// Serves as base for disconnecting from target computer. Defaultly shutdowns both sockets.
        /// </summary>
        public virtual void Disconnect()
        {
            this.Communicator.Shutdown(SocketShutdown.Both);
        }
    }
}
